-- proj: 三丽鸥迷你梦幻岛活动
-- date: 2022/7/28
-- auth: zour
local log = require "mis_log"
local mis_config = require "mis_config"
local mis_data = require "mis_data"
local mis_bridge = require "mis_bridge"
local uu = require "modules.commhm.utils"
local mis_common = require "mis_common"
local mis_calcu = require "mis_calcu"
local t_retCode = mis_config.t_retCode
local t_cache = ngx.shared.misTime
local n_INIT_CODE = 38032637
local n_MAX_CODE = 60466175
local os_date = os.date
local string_match = string.match

--三丽鸥
local M = {
	s_name = string.match(debug.getinfo(1).short_src, '.*/(.*).lua');	-- 模块名称
}

--皮肤礼包预购买（ret{1, 0}分别代表皮肤不可购买， 礼包可购买）
M.sanrio_pre_buy_skin = function ()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local skin_id = tonumber(ngx.ctx.m_params.skin_id)
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf or {}
    --log.debug("sanrio_pre_buy_skin t_sanrioConf="..uu.to_str(mis_data.t_sanrio.t_conf))

    --客户端传参校验
    if not uin or not apiid or not skin_id then 
        log.day('mis_sanrio', 'sanrio_pre_buy_skin|' .. (uin or "nil") ..  '|' ..(apiid or "nil").. '|'
            .. (skin_id or "nil"))
		return t_retCode.n_PARAM_ERR, 'param error'
	end

    local ret = {
        [1] = {
            already_buy = 0,
            cost_coins = 0,
        },
        [2] = {
            already_buy = 0,
            cost_coins = 0,
        },
    }

    --没有购买该礼包信息那就是皮肤和礼包都未购买
    local ok, buy_skin_info = mis_data.get_user():get_sanrio_skin_info()
    if not ok then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    --先算出默认价格，后面再减去皮肤价格
    local skin_info 
    for _, v in pairs(t_sanrioConf) do
        if tonumber(v.skin.skinId)==skin_id then 
            skin_info = v
        end
    end
    if not skin_info then 
        return t_retCode.n_SYS_ERR, 'no skin_info'
    end
    ret[1].cost_coins = skin_info.skin.skinPrice
    ret[2].cost_coins = ret[2].cost_coins + ret[1].cost_coins
    for _, v in pairs(skin_info.gift.goodsList) do
        ret[2].cost_coins = ret[2].cost_coins + v.price
    end
    if not buy_skin_info then 
        return t_retCode.n_OK, ret
    end

    if buy_skin_info[skin_id][1] then
        ret[1].already_buy = 1
        --只要皮肤购买了，就把礼包里皮肤价格减去
        ret[2].cost_coins = ret[2].cost_coins - ret[1].cost_coins
    end
    if buy_skin_info[skin_id][2] then
         ret[2].already_buy = 1
    end

    return t_retCode.n_OK, ret
end

--点击购买三丽鸥某个皮肤或者礼包 buy_type 1买皮肤 2买礼包
M.sanrio_buy_skin = function ()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local skin_id = tonumber(ngx.ctx.m_params.skin_id)
    local buy_type = tonumber(ngx.ctx.m_params.buy_type) 
    local cost_coins = tonumber(ngx.ctx.m_params.cost_coins) 
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf or {}
    --log.debug("sanrio_buy_skin t_sanrioConf="..uu.to_str(mis_data.t_sanrio.t_conf))

    --客户端传参校验
    if not uin or not apiid or not skin_id or not buy_type or not cost_coins then 
        log.day('mis_sanrio', 'sanrio_buy_skin|' .. (uin or "nil") ..  '|'
            ..(apiid or "nil").. '|' .. (skin_id or "nil"))
		return t_retCode.n_PARAM_ERR, 'param error'
	end

    local ok, buy_skin_info = mis_data.get_user():get_sanrio_skin_info()
    if not ok then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    --已经购买过了
    if buy_skin_info and buy_skin_info[skin_id] and buy_skin_info[skin_id][buy_type] then 
        return t_retCode.n_OPER_ERR, 'alreay_buy'
    end

    local skin_info 
    for _, v in pairs(t_sanrioConf) do
        if tonumber(v.skin.skinId)==skin_id then 
            skin_info = v
        end
    end

    if not skin_info then 
        return t_retCode.n_SYS_ERR, 'no skin_info'
    end

    buy_skin_info = buy_skin_info or {}
    buy_skin_info[skin_id] = buy_skin_info[skin_id] or {}
    buy_skin_info[skin_id][buy_type] = {}

    --购买
    local t_add_items = {}
    local must_cost_coins = 0
    if buy_type==2 then 
        --若皮肤已经购买了，则只返回礼包内容
        if buy_skin_info[skin_id][1] then 
            buy_skin_info[skin_id][buy_type] = skin_info.gift
        else
            buy_skin_info[skin_id][buy_type] = skin_info
            buy_skin_info[skin_id][1] = {buy_with_gift=true}
            --带上皮肤
            t_add_items[1] = {}
            t_add_items[1].id = skin_info.skin.skinId
            t_add_items[1].num = 1
            must_cost_coins = must_cost_coins + skin_info.skin.skinPrice
        end

        --物品
        for _, v in pairs(skin_info.gift.goodsList) do
            local insert_t = {}
            insert_t.id = v.id
            insert_t.num = v.num
            table.insert(t_add_items, insert_t)
            must_cost_coins = must_cost_coins + v.price
        end
    
    else 
        buy_skin_info[skin_id][1] = skin_info.skin
        --
        t_add_items[1] = {}
        t_add_items[1].id = skin_info.skin.skinId
        t_add_items[1].num = 1
        must_cost_coins = must_cost_coins + skin_info.skin.skinPrice
    end

    --log.debug("must_cost_coins= "..must_cost_coins)
    if must_cost_coins~=cost_coins then 
        log.day('mis_sanrio', 'sanrio_buy_skin cost error!' .. uin ..  '|' ..apiid.. '|' .. skin_id..'|'
            ..buy_type..'|'..cost_coins..'|'..must_cost_coins )
        return t_retCode.n_WORK_ERR, 'cost_money error!'
    end

    -- 扣迷你币
	local ok2, s_desc2 = mis_bridge.cost_money(uin, nil, must_cost_coins, mis_config.t_costType.n_COIN, 
        'sanrio_buy_skin', mis_common.table_to_json({name = 'sanrio_buy_skin', now = uu.now()}))
    if not ok2 or ok2~=t_retCode.n_OK then 
        log.day('mis_sanrio', '[cost_money error!] sanrio_buy_skin|' .. uin ..  '|' ..apiid.. '|'.."call accout error!"..'|'..uu.to_str(t_add_items)
            .." code="..ok2.." s_desc2="..(s_desc2 or "nil"))
        return t_retCode.n_SYS_ERR, "call account cost_money error!"
    end
    
    --发奖
    local ok3 = mis_bridge.add_items(uin, t_add_items, "mis_sanrio", "mis_sanrio_add_item")
    if ok3~=t_retCode.n_OK then 
        log.day('mis_sanrio', '[add_items error] sanrio_buy_skin|' .. uin ..  '|' ..apiid.. '|'.."call accout error!"..'|'..uu.to_str(t_add_items))
        return t_retCode.n_SYS_ERR, "call account add_items error!"
    end

    local ok4, code = mis_data.get_user():set_sanrio_skin_info(buy_skin_info)
    if not ok4 then 
        log.day('mis_sanrio', 'sanrio_buy_skin|' .. uin ..  '|' ..apiid.. '|' .. skin_id..'|'..(code or "nil"))
        return t_retCode.n_DB_ERR, "set ssdb error"
    end

    return t_retCode.n_OK, t_add_items
end

M.sanrio_reset_skin_info = function ()
    local code mis_data.get_user():set_sanrio_skin_info(nil)
    return  t_retCode.n_OK, code
end

--[[
local serpent = require "resty.serpent"
M.sanrio_get_score_progress = function ()
    local t_sanrioConf 	= mis_data.t_concert.t_conf or {}
    log.debug("t_sanrioConf="..serpent.block(t_sanrioConf.t_taskList ))
    return  t_retCode.n_OK
end
--]]

--三丽鸥二期参考配置
local Act_37 = {
    control = 1,        --总控 0：关闭， 1：开启
    versionMin = '0.0.0';                           	-- 最低版本限制
	startTime = '2022-01-01';                       	-- 活动开启时间
	endTime = '2023-01-01';                         	-- 活动结束时间		
    task_list = {
        [1] = {     
            task_id = 1;                         		       					
            name = "每日登陆游戏";
            daily = 1;
            event = 18;                           	
            target = 1;                             --1次     				
            bonus = {                               
                {itemId = '三丽鸥积分', num = 10};
            };
        };
        [2] = {   
            task_id = 2;                          		         					
            name = "每日梦幻岛游玩";
            daily = 1;
            event = 25;                           	
            target = 5;                             --5分钟     				
            bonus = {                               
                {itemId = '三丽鸥积分', num = 10};
            };
        };
        [3] = {   
            task_id =3,                              		          					
            name = "分享1次梦幻密语";
            daily = 1;
            event = 29;                           	
            target = 1;                             --1次				
            bonus = {                               
                {itemId = '三丽鸥积分', num = 10};
            };
        };
        [4] = {      
            task_id = 4,                           		          					
            name = "使用1次梦幻密语";
            daily = 1;
            event = 28;                           	
            target = 1;                             --1次数     				
            bonus = {                               
                {itemId = '三丽鸥积分', num = 10};
            };
        };
    },
    --普通奖励
    normal_rewards = {
        [1] = {
            item_id = 12345,    --奖励物品ID
            item_nums = 1,      --数量
            item_score = 10,    --可领取时所需分数
        },
        [2] = {
            item_id = 54321,
            item_nums = 1,
            item_score = 20,   
        },
    },
    --进阶奖励
    advance_rewards = {
        [1] = {
            item_id = 6789,
            item_nums = 1,
            item_score = 10,  
        },
        [2] = {
            item_id = 9876,
            item_nums = 1,
            item_score = 20,   
        },  
    },
    --进阶奖励购买金额
    advance_rewards_cost = 1,
    t_codePrefix = {
        "花小楼","迷斯拉","兔美美","熊孩子","卡卡","妮妮","胖哒","月无双",
        "蛙太郎","古筝","二胡","唢呐","琵琶","笛子","鼓"
    },
}

--=====================================================================================
local function new_sanrio_data(t_sanrioConf)
    local ret = {}
    ret.total_score = 0
    ret.is_buy_advance = 0
    ret.normal_rewards = {}
    ret.advance_rewards = {}
    ret.task_progress = {}
    ret.events_finish_times = {}
    for _, v in ipairs(t_sanrioConf.normal_rewards) do
        local one_reward = {}
        one_reward.item_id = v.item_id
        one_reward.item_nums = v.item_nums
        one_reward.item_score = v.item_score
        one_reward.item_status = 0
        table.insert(ret.normal_rewards, one_reward)
    end
    for _, v in ipairs(t_sanrioConf.advance_rewards) do
        local one_reward = {}
        one_reward.item_id = v.item_id
        one_reward.item_nums = v.item_nums
        one_reward.item_score = v.item_score
        one_reward.item_status = 0
        table.insert(ret.advance_rewards, one_reward)
    end

    --任务数据
    --log.debug("t_sanrioConf.task_list="..uu.to_str(t_sanrioConf.task_list))
    for _, v in ipairs(t_sanrioConf.task_list) do
        local task = {}
        task.task_id = v.task_id
        task.name = v.name
        task.daily = v.daily
        task.event = v.event
        task.target = v.target
        task.bonus = v.bonus
        task.status = 0
        table.insert(ret.task_progress, task)
        ret.events_finish_times[task.event] = 0
    end

    ret.update_ts = t_sanrioConf.update_ts

    return ret
end

local function update_sanrio_config(t_sanrioConf, sanrio_data)
    for k, v in ipairs(t_sanrioConf.normal_rewards) do
        if not sanrio_data.normal_rewards[k] then 
            sanrio_data.normal_rewards[k] = {}
            sanrio_data.normal_rewards[k].item_status = 0
        end
        sanrio_data.normal_rewards[k].item_id = v.item_id
        sanrio_data.normal_rewards[k].item_nums = v.item_nums
        sanrio_data.normal_rewards[k].item_score = v.item_score
    end
    for k, v in ipairs(t_sanrioConf.advance_rewards) do
        if not sanrio_data.advance_rewards[k] then 
            sanrio_data.advance_rewards[k] = {}
            sanrio_data.advance_rewards[k].item_status = 0
        end
        sanrio_data.advance_rewards[k].item_id = v.item_id
        sanrio_data.advance_rewards[k].item_nums = v.item_nums
        sanrio_data.advance_rewards[k].item_score = v.item_score
    end

    --任务数据
    --log.debug("t_sanrioConf.task_list="..uu.to_str(t_sanrioConf.task_list))
    for k, v in ipairs(t_sanrioConf.task_list) do
        if not sanrio_data.task_progress[k] then 
            sanrio_data.task_progress[k] = {}
            sanrio_data.task_progress[k].status = 0
        end
        sanrio_data.task_progress[k].task_id = v.task_id
        sanrio_data.task_progress[k].name = v.name
        sanrio_data.task_progress[k].daily = v.daily
        sanrio_data.task_progress[k].event = v.event
        sanrio_data.task_progress[k].target = v.target
        sanrio_data.task_progress[k].bonus = v.bonus
    end

    sanrio_data.update_ts = t_sanrioConf.update_ts
    return sanrio_data
end 

--请求三丽鸥任务状态面板
--参数： 无
--返回值
--[[
    {
    msg = {
        normal_rewards = {
            [1] = {
                item_id=54321, item_nums=1, item_status=1, item_score=20,
            },
            [2] = {
                item_id=12345, item_nums=1, item_status=2, item_score=10,
            },
        },
        events_finish_times = {
            [28]=0, [29]=1, [25]=0, [18]=1,
        },
        advance_rewards = {
            [1] = {
                item_id=9876, item_nums=1, item_status=1, item_score=20,
            },
            [2] = {
                item_id=6789, item_nums=1, item_status=1, item_score=10,
            },
        },
        task_progress = {
            [1] = {
                bonus = {
                    [1] = {
                        num=10, itemId="三丽鸥积分",
                    },
                },
                daily=1, event=18, status=1, name="每日登陆游戏", target=1, task_id=1,
            },
            [4] = {
                bonus = {
                    [1] = {
                        num=10, itemId="三丽鸥积分",
                    },
                },
                daily=1, event=28, status=0, name="使用1次梦幻密语", target=1, task_id=4,
            },
            [2] = {
                bonus = {
                    [1] = {
                        num=10, itemId="三丽鸥积分",
                    },
                },
                daily=1, event=25, status=0, name="每日梦幻岛游玩", target=5, task_id=2,
            },
            [3] = {
                bonus = {
                    [1] = {
                        num=10, itemId="三丽鸥积分",
                    },
                },
                daily=1, event=29, status=1, name="分享1次梦幻密语", target=1, task_id=3,
            },
        },
        _t_=1658405368, total_score=20, _k_=1000, is_buy_advance=1,
    },
    ret=0,
}
    1.normal_rewards 基础奖励:
        item_status:0不可领 1可领取 2已领取
        item_id:物品ID
        item_nums：数量
        item_score：可领取时所需积分
    2.advance_rewards 进阶奖励 [字段含义同normal_rewards]
    3.task_progress：[task_id].status 0未完成 1已完成 其余皆同配置含义相同
    4.total_score目前总分
    5.is_buy_advance是否购买了进阶奖励 0未购买 1已购买
]]
M.sanrio_check_limit = function ()
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local ver = ngx.ctx.m_params.ver
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf 

    local _check, _info = mis_calcu.check_limit(t_sanrioConf, apiid, ver)
    if not _check then 
        return t_retCode.n_AUTH_ERR, _info
    end

    return t_retCode.n_OK
end

local function check_score_rewards(sanrio_data)
    local update = false
    --达到奖励分数的物品
    for _, v in pairs(sanrio_data.normal_rewards) do
        if v.item_status==0 and sanrio_data.total_score>=v.item_score then 
            v.item_status = 1
            update = true
        end
    end
    if sanrio_data.is_buy_advance == 1 then 
        for _, v in pairs(sanrio_data.advance_rewards) do
            if v.item_status==0 and sanrio_data.total_score>=v.item_score then 
                v.item_status = 1
                update = true
            end
        end
    end   

    return sanrio_data, update 
end

M.sanrio_task_status = function ()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf 
    --log.debug("t_sanrioConf="..uu.to_str(t_sanrioConf))

    if (not uin) or (not apiid) or (not t_sanrioConf) then 
        return t_retCode.n_PARAM_ERR, 'param error'
    end
    
    local ok, sanrio_data = mis_data.get_user():get_sanrio_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    --是否第一次拉取该活动
    if (not sanrio_data) or (not sanrio_data.update_ts) or (not sanrio_data.normal_rewards)
    or (not sanrio_data.advance_rewards) or (not sanrio_data.task_progress) then 
        sanrio_data = new_sanrio_data(t_sanrioConf)
    end
    --是否更新了配置
    local update_config = false
    if sanrio_data.update_ts~=t_sanrioConf.update_ts then 
        update_config = true
        sanrio_data = update_sanrio_config(t_sanrioConf, sanrio_data)
    end
    local update = false
    sanrio_data, update = check_score_rewards(sanrio_data)
    if update then 
        update_config = true
    end

    --按时间复位任务检测
    for _, v in pairs(sanrio_data.task_progress) do
        if v.daily and v.status~=0 then 
            if mis_calcu.check_task_reset(v) then 
                v.finish_ts = nil
                v.status = 0
            end
        end
    end
   
    --每日登录触发
    for _, v  in pairs(sanrio_data.task_progress) do
        if v.event==18 and v.status==0 then
            --这里set过下面就不set了 
            update_config = false
            M.sanrio_finish_task(18, 1, sanrio_data)
            break
        end
    end

    if update_config then 
        local ok2, code = mis_data.get_user():set_sanrio_data(sanrio_data)
        if not ok2 then 
            log.day('mis_sanrio', 'sanrio_task_status set_sanrio_data error!|' .. uin ..  '|' ..apiid.. '|'..(code or "nil"))
            return t_retCode.n_DB_ERR, "set ssdb error"
        end
    end
    
    return  t_retCode.n_OK, sanrio_data
end

--一键领取
--参数： 无
--返回值：
--[[
{
    msg = {
        rewards_list = {
            [1] = {
                num=1, id=12345,
            },
        },
        advance_list = {
            [1] = {
                num=1, id=6789,
            },
            [2] = {
                num=1, id=9876,
            },
        },
        is_buy_advance=0,
    },
    ret=0,
}
    1.rewards_list:可领取物品内容
    2.advance_list进阶奖励内容[目前还不能领，购买进阶奖励后，该字段为空table,内容都会放入rewards_list里]
    3.is_buy_advance是否购买了进阶奖励 0未购买 1已购买
    4.item_status:0不可领 1可领取 2已领取
]]
M.sanrio_get_rewards = function ()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)

    local ok, sanrio_data = mis_data.get_user():get_sanrio_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not sanrio_data then 
        return t_retCode.n_WORK_ERR, '[rewards] no sanrio_data!'
    end

    local ret = {}
    ret.rewards_list = {}
    ret.advance_list = {}
    ret.is_buy_advance = sanrio_data.is_buy_advance

    for _, v in ipairs(sanrio_data.normal_rewards or {}) do
        if v.item_status==1 then
            local item = {}
            item.id = v.item_id
            item.num = v.item_nums
            v.item_status = 2
            table.insert(ret.rewards_list, item)
        end
    end
    --未买进阶奖励则放入进阶奖励表中
    if sanrio_data.is_buy_advance and sanrio_data.is_buy_advance==1 then 
        for _, v in ipairs(sanrio_data.advance_rewards or {}) do
            if v.item_status==1 then
                local item = {}
                item.id = v.item_id
                item.num = v.item_nums
                v.item_status = 2
                table.insert(ret.rewards_list, item)
            end
        end
    else
        for _, v in ipairs(sanrio_data.advance_rewards or {}) do
            if v.item_status==0 and sanrio_data.total_score>=v.item_score then
                local item = {}
                item.id = v.item_id
                item.num = v.item_nums
                table.insert(ret.advance_list, item)
            end
        end
    end

    if #ret.rewards_list==0 then 
        return t_retCode.n_NO_DATA, '[rewards] no rewards_data!'
    end

    --账号服发奖
    local ok2 = mis_bridge.add_items(uin, ret.rewards_list, "mis_sanrio", "mis_sanrio_add_item")
    if ok2~=t_retCode.n_OK then 
        log.day('mis_sanrio', '[sanrio_get_rewards add_items error] sanrio_get_rewards|' .. uin ..  '|' ..apiid.. '|'.."call accout error!"..'|'..uu.to_str(ret.rewards_list))
        return t_retCode.n_SYS_ERR, "call account add_items error!"
    end

    --奖励成功才写入ssdb
    local ok3, code = mis_data.get_user():set_sanrio_data(sanrio_data)
    if not ok3 then 
        log.day('mis_sanrio', 'sanrio_get_rewards set_sanrio_data error!|' .. uin ..  '|' ..apiid.. '|'..(code or "nil"))
        return t_retCode.n_DB_ERR, "set ssdb error"
    end

    --埋点数据
    if ret.rewards_list and #ret.rewards_list>0 then 
        log.remote_pure_day("neverland_receive", mis_common.table_to_json({
            ip = ngx.ctx.m_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil",
            uin = uin,
            time = ngx.ctx.m_params.createTime or uu.now(),
            country = ngx.ctx.m_params.country or 'nil',
            apiid = ngx.ctx.m_params.apiid or 'nil',
            ver = ngx.ctx.m_params.ver or 'nil',
            lang = ngx.ctx.m_params.lang or 'nil',

            key = 'getaward',
            type = "neverland_receive",
            bonus = ret.rewards_list,
        }))
    end 

    log.day('mis_sanrio_ok', 'sanrio_get_rewards |apiid='..apiid..' |uin='..uin.." |ver="..(ngx.ctx.m_params.ver or 'nil')
        ..' |bonus='..uu.to_str(ret.rewards_list))

    return  t_retCode.n_OK, ret
end

--购买进阶奖励 
--参数：无
--返回值：0 or 错误码
M.sanrio_buy_advace = function()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf
    --log.debug("t_sanrioConf="..uu.to_str(t_sanrioConf))
    --local cost_coins = tonumber(ngx.ctx.m_params.cost_coins)
    
    local ok, sanrio_data = mis_data.get_user():get_sanrio_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not sanrio_data then 
        return t_retCode.n_WORK_ERR, '[rewards] no sanrio_data!'
    end
    
    --
    if sanrio_data.is_buy_advance and sanrio_data.is_buy_advance==1 then 
        return t_retCode.n_OPER_ERR, "already_buy_advance"
    end
    --log.debug("cost_coins=".. (cost_coins or "nil"))
    --log.debug("sanrio_data.advance_rewards_cost="..(t_sanrioConf.advance_rewards_cost or "nil"))
    if not t_sanrioConf.advance_rewards_cost or (not tonumber(t_sanrioConf.advance_rewards_cost)) then 
        return t_retCode.n_OPER_ERR, "cost_money error!"
    end
    local cost_coins = tonumber(t_sanrioConf.advance_rewards_cost)
    -- 扣迷你币 id为1[自定义]代表是买进阶奖励
    local ext = mis_common.table_to_json({name = 'sanrio_buy_skin', now = uu.now(), items={id=1, price=cost_coins, num=1} })
	local ok2, s_desc2 = mis_bridge.cost_money(uin, nil, cost_coins, mis_config.t_costType.n_COIN, 'sanrio_buy_skin', ext)
    --log.debug("ext="..ext)
    if not ok2 or ok2~=t_retCode.n_OK then 
        log.day('mis_sanrio', '[cost_money error!] sanrio_buy_advace|' .. uin ..  '|' ..apiid.. '|'.."call accout error!"..'|'..uu.to_str(ext)
            .." code="..ok2.." s_desc2="..(s_desc2 or "nil"))
        return t_retCode.n_SYS_ERR, "call account cost_money error!"
    end

    --将进阶后可购买的物品状态修改
    sanrio_data.is_buy_advance = 1
    for _, v in pairs(sanrio_data.advance_rewards) do
        if v.item_status==0 and sanrio_data.total_score>=v.item_score then 
            v.item_status = 1
        end
    end

    --购买成功才写入ssdb
    local ok3, code = mis_data.get_user():set_sanrio_data(sanrio_data)
    if not ok3 then 
        log.day('mis_sanrio', 'sanrio_buy_advace set_sanrio_data error!|' .. uin ..  '|' ..apiid.. '|'..(code or "nil"))
        return t_retCode.n_DB_ERR, "set ssdb error"
    end

    --埋点数据
    log.remote_pure_day("neverland_advanced", mis_common.table_to_json({
        ip = ngx.ctx.m_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil",
        uin = uin,
        time = ngx.ctx.m_params.createTime or uu.now(),
        country = ngx.ctx.m_params.country or 'nil',
        apiid = ngx.ctx.m_params.apiid or 'nil',
        ver = ngx.ctx.m_params.ver or 'nil',
        lang = ngx.ctx.m_params.lang or 'nil',

        key = 'getaward',
        type = "neverland_advanced",
        coin = cost_coins,
    }))

    log.day('mis_sanrio_ok', 'sanrio_buy_advace |apiid='..apiid..' |uin='..uin.." |ver="..(ngx.ctx.m_params.ver or 'nil')
        ..' |cost_coins='..cost_coins)

    return  t_retCode.n_OK
end

--上报完成某个任务
--参数: 
    --times：完成次数 [每日登录X分钟，就需要上报X，如5分钟就传5；]
    --event:事件类型：该任务配置表上的event类型
--返回值：0 or 错误码
M.sanrio_finish_task = function(event_id, count, sanrio_data_info, task_uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local event = tonumber(ngx.ctx.m_params.event)
    if event_id then 
        event = event_id
    end
    local times = tonumber(ngx.ctx.m_params.times)
    if count then 
        times = count
    end
    local uin =  tonumber(ngx.ctx.m_params.uin)
    if task_uin then 
        uin = task_uin
    end
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf
    
    if (not apiid) or (not event) or (not times) or (not uin) or (not t_sanrioConf) then 
		return t_retCode.n_PARAM_ERR, 'param error'
	end

    local ok, sanrio_data 
    sanrio_data = sanrio_data_info
    if not sanrio_data then 
        ok, sanrio_data = mis_data.get_user(uin):get_sanrio_data()
        if ok~=t_retCode.n_OK then
            return t_retCode.n_SYS_ERR, 'ssdb error'
        end
    end
    if not sanrio_data then 
        sanrio_data = new_sanrio_data(t_sanrioConf)
    end
   
    sanrio_data.events_finish_times[event] = sanrio_data.events_finish_times[event] + times
    
    local add_score = 0
    local rewards = {}
    --增加总分并且对任务改变状态
    for _, v in pairs(sanrio_data.task_progress) do
        if v.status==0 and event==v.event and sanrio_data.events_finish_times[event]>=v.target then 
            v.status = 1
            v.finish_ts = uu.now()
            add_score = add_score + v.bonus[1].num
            sanrio_data.total_score = sanrio_data.total_score + v.bonus[1].num  
        end
        --这里返回的是三丽鸥积分
        rewards = {id=v.bonus[1].itemId, num=add_score }
    end 
    --log.debug("sanrio_data.task_progress="..uu.to_str(sanrio_data.task_progress))

    if add_score==0 then 
        return t_retCode.n_WORK_ERR, '[finish] no finish task!'
    end

    --达到奖励分数的物品
    sanrio_data = check_score_rewards(sanrio_data)

    local ok2, code = mis_data.get_user(uin):set_sanrio_data(sanrio_data)
    if not ok2 then 
        log.day('mis_sanrio', 'sanrio_finish_task set_sanrio_data error!|' .. uin ..  '|' ..apiid.. '|'..(code or "nil"))
        return t_retCode.n_DB_ERR, "set ssdb error"
    end

    --埋点数据
    log.remote_pure_day("neverland_point", mis_common.table_to_json({
        ip = ngx.ctx.m_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil",
        uin = uin,
        time = ngx.ctx.m_params.createTime or uu.now(),
        country = ngx.ctx.m_params.country or 'nil',
        apiid = ngx.ctx.m_params.apiid or 'nil',
        ver = ngx.ctx.m_params.ver or 'nil',
        lang = ngx.ctx.m_params.lang or 'nil',

        key = 'finish',
        type = "neverland_point",
        point = sanrio_data.total_score,
    }))

    log.day('mis_sanrio_ok', 'sanrio_finish_task |apiid='..apiid..' |uin='..uin.." |ver="..(ngx.ctx.m_params.ver or 'nil')
        ..' |event='..event.." |add_score="..add_score.." |total_score="..sanrio_data.total_score.." |times="..times
        .." |event_times_data="..sanrio_data.events_finish_times[event])

    return t_retCode.n_OK, rewards
end

--复位数据
--参数： 无
M.sanrio_reset_data = function ()
    local code = mis_data.get_user():set_sanrio_data(nil)
    return  t_retCode.n_OK, code
end

--三丽鸥获取地图数据
M.sanrio_get_player_info = function ()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local apiid = tonumber(ngx.ctx.m_params.apiid)
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf or Act_37


    local id1 = 1000010
    local id2 = 84134114362578
    local ret, rst = mis_bridge.get_cloud_dhs_data(84134114362578, "level", ngx.ctx.m_params.uin)
    --log.debug("ret="..ret)
    --log.debug("rst="..(rst or "nil"))
    if not ret then
        return t_retCode.n_OK
    end

    return t_retCode.n_OK
end


--------------------------------------------------------------
-- 说明：三丽鸥请求密码
-- 返回：n					状态码
--		ts 					描述
M.sanrio_secret_code = function()
    local uin =  tonumber(ngx.ctx.m_params.uin)
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf

    if (not uin) or (not t_sanrioConf) then 
		return t_retCode.n_PARAM_ERR, 'param error'
	end

	-- 加个锁，防止刷票
	local b_ok, s_desc = t_cache:add("sanrio_request_code" .. uin, 1, 0.2)
	if not b_ok then
		log.day("mis_sanrio" ,"sanrio_request_code".. "request frequently".. uin.." "..uu.to_str(s_desc))
		return t_retCode.n_OPER_ERR, 'request frequently'
	end

    local ok, sanrio_data = mis_data.get_user():get_sanrio_data()
    if ok~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not sanrio_data then 
        sanrio_data = new_sanrio_data(t_sanrioConf)
    end

    --一天只能申请一个码
    if sanrio_data.secret_data and os_date("%Y%m%d", sanrio_data.secret_data.ctime) == os_date("%Y%m%d") then 
        return t_retCode.n_OK, { code = sanrio_data.secret_data.code }
    end
    --log.debug("t_sanrioConf.share_cfg.t_codePrefix="..uu.to_str(t_sanrioConf.share_cfg.t_codePrefix))
    --log.debug("t_sanrioConf.share_cfg.t_codePrefix2222="..uu.to_str(t_sanrioConf.share_cfg.codePrefix))
	local s_code, s_reason = mis_calcu.new_share_code("mis_sanrio", t_sanrioConf.share_cfg.t_codePrefix, n_INIT_CODE, n_MAX_CODE)
	if s_code == nil then
		log.day("mis_sanrio","sanrio_request_code ".."sanrio_secret_code error".. uin..uu.to_str(s_reason))
		return t_retCode.n_SYS_ERR, "new_share_code error"
	end

    local t_codeData = {ctime = uu.now(), uin = uin, exchange = 0, exchange_users = {}}
    b_ok, s_desc = mis_data.get_user():set_secret_code(s_code, t_codeData, 1)
	if b_ok ~= t_retCode.n_OK then
		log.day("mis_sanrio", "sanrio_request_code".."save sys code error".. uin.. uu.to_str(b_ok).. uu.to_str(s_desc))
		return b_ok, s_desc
	end
	
    sanrio_data.secret_data = {ctime = uu.now(), code = s_code}
    b_ok, s_desc = mis_data.get_user():set_sanrio_data(sanrio_data)
	if b_ok ~= t_retCode.n_OK then
		log.day("mis_sanrio", "sanrio_request_code".. "save user code error".. uin.. uu.to_str(b_ok).. uu.to_str(s_desc).. uu.to_str(sanrio_data.secret_data))
		return b_ok, s_desc
	end

    log.day('mis_sanrio_ok', 'sanrio_secret_code |apiid='..(ngx.ctx.m_params.apiid or 'nil')..' |uin='..uin.." |ver="..(ngx.ctx.m_params.ver or 'nil')
        .." |new_code="..uu.to_str(s_code))

	return t_retCode.n_OK, { code = s_code }
end


--------------------------------------------------------------
-- 说明：三丽鸥密码兑换
-- 返回：n					状态码
--		ts 					描述
M.sanrio_code_exchange = function()
	local t_params 	= ngx.ctx.t_params
	local n_uin 	= t_params.uin
	local s_code 	= t_params.code
    local t_sanrioConf 	= mis_data.t_sanrio.t_conf 

    if not t_sanrioConf then 
		return t_retCode.n_PARAM_ERR, 'param error'
	end

	-- 判断参数是否有效
	if not s_code or string_match(s_code, "^%s*$") ~= nil then
		log.day("mis_sanrio", "sanrio_code_exchange".."s_code empty"..n_uin..uu.to_str(s_code))
		return t_retCode.n_PARAM_ERR, 'code empty'
	end

    local b_ok, t_codeData = mis_data.get_user():get_secret_code(s_code)
	if b_ok ~= t_retCode.n_OK then
		log.day("mis_sanrio", "sanrio_code_exchange".."get_secret_code error".. n_uin.. uu.to_str(b_ok).. uu.to_str(t_codeData))
		return b_ok, t_codeData
	end

	-- 密码不存在
	if t_codeData.uin == nil then
		--log.day("mis_sanrio", "sanrio_code_exchange".."code not exists".. n_uin.."|"..uu.to_str(t_codeData))
		return t_retCode.n_CONCERT_CODE_INVALID, "code not exists"
	end

	if t_codeData.uin == n_uin then
		--log.day("mis_sanrio", "sanrio_code_exchange".. "can't exchange self".. n_uin.."|"..uu.to_str(t_codeData))
		return t_retCode.n_CONCERT_CODE_SELF_LIMIT, "can't exchange self"
	end

	-- 只能兑换2次
	if t_codeData.exchange >= 2 then
		--log.day("mis_sanrio", "sanrio_code_exchange".."exchange excess"..n_uin.."|"..uu.to_str(t_codeData))
		return t_retCode.n_CONCERT_CODE_EXCESS, "exchange excess"
	end
	
	-- 一个用户同一个码只能兑换一次
	if t_codeData.exchange_users and t_codeData.exchange_users[n_uin] then
		--log.day("mis_sanrio", "sanrio_code_exchange".. "exchange repeated".. n_uin.."|"..uu.to_str(t_codeData))
		return t_retCode.n_CONCERT_CODE_REPEATED, "exchange repeated"
	end

	-- 已过期
	if os_date("%Y%m%d", t_codeData.ctime) ~= os_date("%Y%m%d") then
		--log.day("mis_sanrio", "sanrio_code_exchange".."code expire".. n_uin.."|"..uu.to_str(t_codeData))
		return t_retCode.n_CONCERT_CODE_EXPIRE, "code expire"
	end

	t_codeData.exchange = t_codeData.exchange + 1
	t_codeData.exchange_users = t_codeData.exchange_users or {}
	t_codeData.exchange_users[n_uin] = 1

    local ok, s_desc = mis_data.get_user():set_secret_code(s_code, t_codeData)
	if ok ~= t_retCode.n_OK then
		log.day("mis_sanrio", "sanrio_code_exchange".."save sys code error".. n_uin.. uu.to_str(ok).. uu.to_str(s_desc))
		return b_ok, s_desc
	end

    local ok2, sanrio_data = mis_data.get_user():get_sanrio_data()
    if ok2~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not sanrio_data then 
        sanrio_data = new_sanrio_data(t_sanrioConf)
    end

    --使用者触发奖励
    local rewards = {}
    for _, v  in pairs(sanrio_data.task_progress) do
        if v.event==28 and v.status==0 then 
            local ok, one_rewards = M.sanrio_finish_task(28, 1, sanrio_data)
            table.insert(rewards, one_rewards)
            break
        end
    end

    -- 分享者发奖励
    local ok3, share_sanrio_data = mis_data.get_user(t_codeData.uin):get_sanrio_data()
    if ok3~=t_retCode.n_OK then
        return t_retCode.n_SYS_ERR, 'ssdb error'
    end
    if not share_sanrio_data then 
        share_sanrio_data = new_sanrio_data(t_sanrioConf)
    end
    for _, v  in pairs(share_sanrio_data.task_progress) do
        if v.event==29 and v.status==0 then 
            M.sanrio_finish_task(29, 1, share_sanrio_data, t_codeData.uin)
            break
        end
    end

    log.day('mis_sanrio_ok', 'sanrio_secret_code |apiid='..(ngx.ctx.m_params.apiid or 'nil').." |ver="..(ngx.ctx.m_params.ver or 'nil')
        .." |exchange_uin="..n_uin.." |t_codeData=".. uu.to_str(t_codeData))

	return t_retCode.n_OK, rewards
end

return M